package com.apes.scm.masterdata.product.model;

import com.apes.framework.jpa.DefaultPersistListener;
import com.apes.framework.jpa.Model;
import com.apes.framework.jpa.comment.Comment;
import com.apes.framework.jpa.generator.ApesGenerator;
import com.apes.framework.plugin.soe.annotations.State;
import com.apes.framework.plugin.soe.annotations.States;
import com.apes.framework.plugin.soe.metadata.BusinessAttributeValue;
import com.apes.framework.util.ApesConst;
import com.apes.framework.util.Arith;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.SelectBeforeUpdate;

import javax.persistence.*;

/**
 * 功能：计量单位
 *
 * @author xul
 * @create 2018-01-30 14:28
 */
@Getter
@Setter
@SelectBeforeUpdate
@DynamicInsert
@DynamicUpdate
@Entity
@EntityListeners(DefaultPersistListener.class)
@Table(name = ProductUom.CONST_TABLE_NAME)
public class ProductUom extends Model {
    public static final String CONST_TABLE_NAME = "mas_product_uom";

    @Id
    @Column(name = "id")
    @ApesGenerator(code = CONST_TABLE_NAME, name = "计量单位")
    @Comment("编码")
    private long id;

    @Column(name = "name", nullable = false, length = 60)
    @Comment("名称")
    private String name; //名称

    @Column(name = "valid", nullable = false)
    @Comment("有效标记")
    private boolean valid = true; //有效

    /**
     * 该值大于零
     * reference: factor = 1
     * bigger: 0 < factor < 1
     * smaller: factor > 1
     */
    @Column(name = "factor", nullable = false, columnDefinition = ApesConst.FIELD_ROUND_16_8)
    @Comment("比例")
    private double factor; //比例，例如: 1*(参考单位) = 比例 * （本单位）

    @Column(name = "rounding", nullable = false, columnDefinition = ApesConst.FIELD_ROUND_16_8)
    @Comment("舍入精度")
    private double rounding; //舍入精度：数点后保留几位

    @States(name = "类型", values = {
            @State(id = "reference", name = "参考计量单位"),
            @State(id = "bigger", name = "大于参考计量单位"),
            @State(id = "smaller", name = "小于参考计量单位")})
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "uom_type", referencedColumnName = "id", nullable = false)
    private BusinessAttributeValue uomType; //类型：（'reference'：这个类别的参考计量单位），（'bigger'：大于参考计量单位），（'smaller'：小于参考计量单位）

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "uom_category_id", referencedColumnName = "id", nullable = false)
    @Comment("类别")
    private ProductUomCategory uomCategory; //类别

    @Column(name = "purchase_First", nullable = false, columnDefinition = ApesConst.FIELD_BOOLEAN_FALSE)
    @Comment("采购优先")
    private boolean purchaseFirst = false; //采购优先

    @Column(name = "sale_First", nullable = false, columnDefinition = ApesConst.FIELD_BOOLEAN_FALSE)
    @Comment("销售优先")
    private boolean saleFirst = false; //销售优先

    @Column(name = "transfer_First", nullable = false, columnDefinition = ApesConst.FIELD_BOOLEAN_FALSE)
    @Comment("转储优先")
    private boolean transferFirst = false; //转储优先


    /**
     * 功能：计量单位换算（数量）
     *
     * @param qty   基数
     * @param toUom 默认UoM
     * @param round 是否四舍五入
     * @return
     */
    public double computeQty(double qty, ProductUom toUom, boolean round) {
        if (qty == 0) return qty;
        if(toUom == null) throw new RuntimeException("计量单位换算为空！");
        if (this.getId() == toUom.getId()) return qty;
        if (this.getUomCategory() == null) throw new RuntimeException(String.format("商品计量单位：[ %s - %s ] 类别为空！",  this.id, this.name, toUom.getName()));
        if (toUom.getUomCategory() == null) throw new RuntimeException(String.format("商品计量单位：[ %s - %s ] 类别为空！",  toUom.id, toUom.name, toUom.getName()));
        if (this.getUomCategory().getId() != toUom.getUomCategory().getId()) {
            throw new RuntimeException(String.format("商品计量单位：%s 和 %s 不能转换，类别不同！", this.name, toUom.getName()));
        }
        double amt = qty / this.getFactor();  //参考计量单位
        if (toUom != null) {
            amt = amt * toUom.getFactor();
            if (round) {
                amt = Arith.round(amt, Arith.computeDecimalPlaces(toUom.getRounding()));
            }
        }
        return amt;
    }

    /**
     * 功能：计量单位换算（金额）
     *
     * @param price 基数
     * @param toUom 默认UoM
     * @return
     */
    public double computePrice(double price, ProductUom toUom) {
        if (price == 0) return price;
        if (toUom == null) return price;
        if (this.getId() == toUom.getId()) return price;
        if (this.getUomCategory().getId() != toUom.getUomCategory().getId()) return price;
        double amt = price * this.getFactor();
        if (toUom != null) {
            amt = amt / toUom.getFactor();
        }
        return amt;
    }


}
